<!--- Document Information -----------------------------------------------------

Title:      SubethasmtpFactory.cfc

Author:     Mark Mandel
Email:      mark@compoundtheory.com

Website:    http://www.compoundtheory.com

Purpose:    Factory for getting to Subethasmtp objects

Usage:      

Modification Log:

Name			Date			Description
================================================================================
Mark Mandel		27/06/2006		Created

------------------------------------------------------------------------------->

<cfcomponent name="SubethasmtpService" hint="Factory for getting to Subethasmtp objects">

<cfscript>
	instance = StructNew();
</cfscript>

<cffunction name="dumpvar">
  <cfargument name="var" default="blank">
  <cfargument name="abort" default="true">
  <cftry>
	  <cfdump var="#var#">
	<cfcatch>
	  <cfset writeoutput(cfcatch.Message & " " & cfcatch.Detail & " " & cfcatch.TagContext[1].line & " " & cfcatch.stacktrace) />
	</cfcatch>
	</cftry>
	<cfif arguments.abort>
	  <cfabort />
	</cfif>
</cffunction>

<!------------------------------------------- PUBLIC ------------------------------------------->

<cffunction name="init" hint="Constructor: Loads the subethasmtp.cfg.xml from here, and any *.hbm.xml files that are in this directory" access="public" returntype="SubethasmtpService" output="false">
	<cfargument name="listenport" default="2525" />
	<cfset var wiser = "" />
	<cflock scope="server" timeout="3">
		<cfif NOT structKeyExists(server,"wiser_supercalifragilistic")>
			<cfset wiser = createObject("component","lib.LibraryLoader").init().create("org.subethamail.wiser.Wiser") /> 
			<cfset server.wiser_supercalifragilistic = wiser />
    	<cfset server.deletedMessageIdList = "" />
		</cfif>
		<cfset this.smtpserver = server.wiser_supercalifragilistic />
	</cflock>
	<cfscript>
//		context = createObject("java","org.subethamail.smtp.server.ConnectionContext").init();
	//	command = createObject("java","org.subethamail.smtp.command.HelpCommand").init();
	//	dumpvar(command.getHelp(javacast("string","HELP")).toOutPutString(),false);
	//	dumpvar(this.smtpserver.getMessages());
    setPort(listenport);
    if(NOT this.smtpserver.getServer().isRunning()) {
	    startserver(arguments.listenport);
    }
    variables.listenport = listenport;
		return this;
	</cfscript>
</cffunction>

<cffunction name="setPort" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfargument name="port" required="Yes">
	<cfscript>
		this.smtpserver.setPort(arguments.port);
	</cfscript>
</cffunction>

<cffunction name="startserver" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfscript>
    try{
			this.smtpserver.start();
    } catch (er Any) {
    	// server started ?
    }
	</cfscript>
</cffunction>

<cffunction name="stopserver" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfscript>
		this.smtpserver.stop();
	</cfscript>
</cffunction>

<cffunction name="messagesToCFstructs" hint="Creates a hibernate object" access="public" returntype="any" output="true">
	<cfargument name="messagesInArray" required="true" />
	<cfscript>
		var messagesArray = arguments.messagesInArray;
		var messages = arrayNew(1);
		var message = "";
		var mimeMessage = "";
		var numMessages = arrayLen(messagesArray);
		var headers = "";
		var header = "";
		var recipients = "";
		var recipientsArray = "";
		var m = 0;
		var content = "";
		var out = createObject("java","java.io.ByteArrayOutputStream").init();
		if(numMessages gt 0) {
			for (m = 1; m lte arrayLen(messagesArray); m=m+1) {
				content = "";
				out.reset();
				message = messagesArray[m];
				mimeMessage = message.getMimeMessage();
				messages[m] = structNew();
				messages[m]["sender"] = message.getEnvelopeSender();
				messages[m]["receiver"] = message.getEnvelopeReceiver();
				messages[m]["headers"] = structNew();
				headers = mimeMessage.getAllHeaders();
				while(headers.hasMoreElements()) {
					header = headers.nextElement();
					messages[m]["headers"][header.getname()] = header.getValue();
				}
				recipients = arrayNew(1);
				recipientsArray = mimeMessage.getAllRecipients();
				for (r = 1; r lte arrayLen(recipientsArray); r=r+1) {
					arrayAppend(recipients,recipientsArray[r].toString());
				}
				messages[m]["recipients"] = recipients;
				messages[m]["subject"] = mimeMessage.getSubject();
				messages[m]["content"] = arrayNew(1);
				mimeMessage.getContent().writeTo(out);
				content = out.toString();
				messages[m]["content"] = reReplaceNoCase(content,".*Content-Transfer-Encoding: quoted-printable(.*)----=.*","\1","all");				
				messages[m]["contentRaw"] = content;				
				messages[m]["contentID"] = toString(mimeMessage.getContentID());
				messages[m]["replyTo"] = mimeMessage.getReplyTo();
				messages[m]["replyTo"] = messages[m]["replyTo"][1].toString();
				messages[m]["sent"] = toString(mimeMessage.getSentDate());
				messages[m]["size"] = toString(mimeMessage.getSize());
				messages[m]["lines"] = toString(mimeMessage.getLineCount());
				messages[m]["messageid"] = toString(mimeMessage.getMessageID());
				messages[m]["received"] = toString(mimeMessage.getReceivedDate());
				messages[m]["encoding"] = toString(mimeMessage.getEncoding());
				messages[m]["disposition"] = toString(mimeMessage.getDisposition());
				messages[m]["contenttype"] = toString(mimeMessage.getContentType());
//				dumpvar(mimeMessage,false);
			}
		}
		return messages;
	</cfscript>
</cffunction>

<cffunction name="getMessages" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfargument name="delayseconds" type="numeric" default="0" />
	<cfscript>
		var messagesArray = this.smtpserver.getMessages();
		var m = 0;
		var thread = "";
		var messageId = "";
		var messages = arrayNew(1);
		var messageIdList = "";
		if(arguments.delayseconds gt 0) {
			thread = createObject( "java", "java.lang.Thread" );
			thread.sleep(delayseconds*1000);
		}
		for (m = 1; m lte arrayLen(messagesArray); m=m+1) {
			messageId = messagesArray[m].getMimeMessage().getMessageId();
			if(NOT listFind(server.deletedMessageIdList,messageId)) {
				if(NOT listFind(messageIdList,messageId)) {
					arrayAppend(messages,messagesArray[m]);
					messageIdList = listAppend(messageIdList,messageId);
				}				
			}
		}
		return messages;
	</cfscript>
</cffunction>

<cffunction name="getMessagesAsStruct" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfargument name="delayseconds" type="numeric" default="0" />
	<cfscript>
		var messagesArray = getMessages(arguments.delayseconds);
		return messagesToCFstructs(messagesArray);		
	</cfscript>
</cffunction>

<cffunction name="findMessages" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfargument name="delayseconds" type="numeric" default="0" />
	<cfargument name="subject" type="string" default="" />
	<cfargument name="sender" type="string" default="" />
	<cfargument name="recipients" type="string" default="" />
	<cfscript>
		var message = "";
		var messages = messagesToCFstructs(getMessages(arguments.delayseconds));
		var hits = arrayNew(1);
		var foundMessageIdList = "";
		var x = 0;
		for(x=1; x lte arrayLen(messages); x = x+1) {
			message = messages[x];
			if(arguments.subject gt "") {
				if(findNoCase(arguments.subject,message["subject"])) {
					if(NOT listFind(foundMessageIdList,message.messageId)) {
						arrayAppend(hits,message);
						foundMessageIdList = listAppend(foundMessageIdList,message.messageId);
					}
				}
			}
			if(arguments.sender gt "") {
				if(findNoCase(arguments.sender,message["sender"])) {
					if(NOT listFind(foundMessageIdList,message.messageId)) {
						arrayAppend(hits,message);
						foundMessageIdList = listAppend(foundMessageIdList,message.messageId);
					}
				}
			}
			if(arguments.recipients gt "") {
				if(findNoCase(arguments.recipients,arrayToList(message["recipients"]))) {
					if(NOT listFind(foundMessageIdList,message.messageId)) {
						arrayAppend(hits,message);
						foundMessageIdList = listAppend(foundMessageIdList,message.messageId);
					}
				}
			}
		}
		return hits;
	</cfscript>
</cffunction>

<cffunction name="deleteFoundMessages" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfargument name="foundMessagesArray" required="true" type="array" />
	<cfscript>
		var messages = arguments.foundMessagesArray;
		var x = 0;
		for(x=1; x lte arrayLen(messages); x = x+1) {
			deleteMessage(messages[x].messageId);
		}
	</cfscript>
</cffunction>


<cffunction name="getMessageCount" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfargument name="delayseconds" type="numeric" default="0" />
	<cfscript>
		var thread = "";
		if(arguments.delayseconds gt 0) {
			thread = createObject( "java", "java.lang.Thread" );
			thread.sleep(delayseconds*1000);
		}
		return arrayLen(getMessages());		
	</cfscript>
</cffunction>


<cffunction name="deleteMessage" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfargument name="messageId" required="true" />
	<cflock scope="server" timeout="3">
	<cfscript>
		server.deletedMessageIdList = listAppend(server.deletedMessageIdList,arguments.messageId);
	</cfscript>
	</cflock>
</cffunction>

<cffunction name="clearMessages" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfscript>
		var messagesArray = getMessages();
		var m = 0;		
		for (m = 1; m lte arrayLen(messagesArray); m=m+1) {
			deleteMessage(messagesArray[m].getMimeMessage().getMessageId());
		}
		return true;
	</cfscript>
</cffunction>

<cffunction name="testmessage" hint="Creates a hibernate object" access="public" returntype="any" output="false">
	<cfargument name="delayseconds" type="numeric" default="0" />
	<cfargument name="subject" default="testing email" />
	<cfargument name="body" default="I like cheese" />
	<cfset var thread = "" />
	<cfmail to="test@test.com" from="anothertester@test.com" subject="#arguments.subject#" server="localhost" port="#variables.listenport#">
	  <cfoutput>#arguments.body#</cfoutput>
	</cfmail>
	<cfscript>
		if(arguments.delayseconds gt 0) {
			thread = createObject( "java", "java.lang.Thread" );
			thread.sleep(delayseconds*1000);
		}
	</cfscript>
</cffunction>

</cfcomponent>